第12周—项目5 迷宫问题之图深度优先遍历解法

问题描述及代码:

 

#ifndef BTREE_H_INCLUDED
#define BTREE_H_INCLUDED
/*   
*烟台大学计控学院    
*作    者:杨征   
*完成日期:2015年11月22日
*问题描述:设计一个程序,采用深度优先遍历算法的思路,解决迷宫问题。 
   (1)建立迷宫对应的图数据结构,并建立其邻接表表示。 
   (2)采用深度优先遍历的思路设计算法,输出从入口(1,1)点到出口(M,N)的所有迷宫路径。 

[模型建立] 
  将迷宫中的每一格作为一个顶点,相邻格子可以到达,则对应的顶点之间存在边相连。 
   例如,下面的迷宫 
这里写图片描述 
 在使用数组表示时,用0表示格子是空地,用1表示格子处是墙,对应的矩阵是:
    int mg[M+2][N+2]=   //迷宫数组
    {
        {1,1,1,1,1,1},
        {1,0,0,0,1,1},
        {1,0,1,0,0,1},
        {1,0,0,0,1,1},
        {1,1,0,0,0,1},
        {1,1,1,1,1,1}
    };•1

于是,从(1,1)到(4,4)的迷宫问题,转化为寻找顶点(1,1)到顶点(4,4)的路径的问题。

*/
#endif // BTREE_H_INCLUDED
#include <stdio.h>
#include <malloc.h>
#define MaxSize 100
#define M 4
#define N 4
//以下定义邻接表类型
typedef struct ANode            //边的结点结构类型
{
    int i,j;                    //该边的终点位置(i,j)
    struct ANode *nextarc;      //指向下一条边的指针
} ArcNode;

typedef struct Vnode            //邻接表头结点的类型
{
    ArcNode *firstarc;          //指向第一条边
} VNode;

typedef struct
{
    VNode adjlist[M+2][N+2];    //邻接表头节点数组
} ALGraph;                      //图的邻接表类型

typedef struct
{
    int i;                      //当前方块的行号
    int j;                      //当前方块的列号
} Box;

typedef struct
{
    Box data[MaxSize];
    int length;                 //路径长度
} PathType;                     //定义路径类型

int visited[M+2][N+2]= {0};
int count=0;
void CreateList(ALGraph *&G,int mg[][N+2])
//建立迷宫数组对应的邻接表G
{
    int i,j,i1,j1,di;
    ArcNode *p;
    G=(ALGraph *)malloc(sizeof(ALGraph));
    for (i=0; i<M+2; i++)                   //给邻接表中所有头节点的指针域置初值
        for (j=0; j<N+2; j++)
            G->adjlist[i][j].firstarc=NULL;
    for (i=1; i<=M; i++)                    //检查mg中每个元素
        for (j=1; j<=N; j++)
            if (mg[i][j]==0)
            {
                di=0;
                while (di<4)
                {
                    switch(di)
                    {
                    case 0:
                        i1=i-1;
                        j1=j;
                        break;
                    case 1:
                        i1=i;
                        j1=j+1;
                        break;
                    case 2:
                        i1=i+1;
                        j1=j;
                        break;
                    case 3:
                        i1=i, j1=j-1;
                        break;
                    }
                    if (mg[i1][j1]==0)                          //(i1,j1)为可走方块
                    {
                        p=(ArcNode *)malloc(sizeof(ArcNode));   //创建一个节点*p
                        p->i=i1;
                        p->j=j1;
                        p->nextarc=G->adjlist[i][j].firstarc;   //将*p节点链到链表后
                        G->adjlist[i][j].firstarc=p;
                    }
                    di++;
                }
            }
}
//输出邻接表G
void DispAdj(ALGraph *G)
{
    int i,j;
    ArcNode *p;
    for (i=0; i<M+2; i++)
        for (j=0; j<N+2; j++)
        {
            printf("  [%d,%d]: ",i,j);
            p=G->adjlist[i][j].firstarc;
            while (p!=NULL)
            {
                printf("(%d,%d)  ",p->i,p->j);
                p=p->nextarc;
            }
            printf("\n");
        }
}
void FindPath(ALGraph *G,int xi,int yi,int xe,int ye,PathType path)
{
    ArcNode *p;
    visited[xi][yi]=1;                   //置已访问标记
    path.data[path.length].i=xi;
    path.data[path.length].j=yi;
    path.length++;
    if (xi==xe && yi==ye)
    {
        printf("  迷宫路径%d: ",++count);
        for (int k=0; k<path.length; k++)
            printf("(%d,%d) ",path.data[k].i,path.data[k].j);
        printf("\n");
    }
    p=G->adjlist[xi][yi].firstarc;  //p指向顶点v的第一条边顶点
    while (p!=NULL)
    {
        if (visited[p->i][p->j]==0) //若(p->i,p->j)方块未访问,递归访问它
            FindPath(G,p->i,p->j,xe,ye,path);
        p=p->nextarc;               //p指向顶点v的下一条边顶点
    }
    visited[xi][yi]=0;
}

int main()
{
    ALGraph *G;
    int mg[M+2][N+2]=                           //迷宫数组
    {
        {1,1,1,1,1,1},
        {1,0,0,0,1,1},
        {1,0,1,0,0,1},
        {1,0,0,0,1,1},
        {1,1,0,0,0,1},
        {1,1,1,1,1,1}
    };
    CreateList(G,mg);
    printf("迷宫对应的邻接表:\n");
    DispAdj(G); //输出邻接表
    PathType path;
    path.length=0;
    printf("所有的迷宫路径:\n");
    FindPath(G,1,1,M,N,path);
    return 0;
}
运行结果:


知识点总结:

综合运用了图的深度和广度遍历

学习心得:

图在日常生活中应用很广泛



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
生成迷宫的一种常见算法是基于深度优先遍历的随机迷宫生成算法。该算法的基本思路是从一个起始点出发,随机选择一个相邻的未被访问过的点,将其标记为已访问,并将两点之间的墙壁打通。然后以新访问的点为起点继续随机选择未访问过的点,直到所有的点都被访问过。 在Java中,可以使用二维数组表示迷宫地图。数组中的每个元素表示一个格子,可以包含四面墙壁状态的信息(例如用0表示墙壁存在,用1表示墙壁不存在),以及是否被访问过的信息(例如用0表示未被访问过,用1表示已被访问过)。以下是一个基于深度优先遍历的随机迷宫生成算法示例代码: ``` java import java.util.Random; public class MazeGenerator { private int width; // 迷宫宽度 private int height; // 迷宫高度 private int[][] maze; // 迷宫地图 private Random random; // 随机数生成器 // 构造函数 public MazeGenerator(int width, int height) { this.width = width; this.height = height; maze = new int[height][width]; random = new Random(); generateMaze(0, 0); // 从左上角的格子开始生成迷宫 } // 生成迷宫 private void generateMaze(int row, int col) { maze[row][col] = 1; // 标记当前格子已访问过 // 随机顺序访问邻居格子 int[] directions = {0, 1, 2, 3}; // 上、右、下、左 shuffle(directions); // 随机打乱顺序 for (int direction : directions) { int newRow = row; int newCol = col; switch (direction) { case 0: // 上 newRow--; break; case 1: // 右 newCol++; break; case 2: // 下 newRow++; break; case 3: // 左 newCol--; break; } // 判断新格子是否在迷宫范围内且未被访问过 if (newRow >= 0 && newRow < height && newCol >= 0 && newCol < width && maze[newRow][newCol] == 0) { // 打通两格之间的墙壁 if (direction == 0) { // 上 maze[row][col] &= ~1; // 当前格子的上墙壁打通 maze[newRow][newCol] &= ~4; // 新格子的下墙壁打通 } else if (direction == 1) { // 右 maze[row][col] &= ~2; // 当前格子的右墙壁打通 maze[newRow][newCol] &= ~8; // 新格子的左墙壁打通 } else if (direction == 2) { // 下 maze[row][col] &= ~4; // 当前格子的下墙壁打通 maze[newRow][newCol] &= ~1; // 新格子的上墙壁打通 } else if (direction == 3) { // 左 maze[row][col] &= ~8; // 当前格子的左墙壁打通 maze[newRow][newCol] &= ~2; // 新格子的右墙壁打通 } generateMaze(newRow, newCol); // 递归访问新格子 } } } // 随机打乱数组元素的顺序 private void shuffle(int[] array) { for (int i = array.length - 1; i > 0; i--) { int j = random.nextInt(i + 1); int temp = array[i]; array[i] = array[j]; array[j] = temp; } } // 打印迷宫地图 public void printMaze() { for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { System.out.print(maze[i][j] + " "); } System.out.println(); } } // 测试代码 public static void main(String[] args) { MazeGenerator generator = new MazeGenerator(10, 10); generator.printMaze(); } } ``` 运行上述代码,可以生成一个10x10的迷宫地图,并打印出来。你可以根据自己的需要修改迷宫大小,或者将迷宫地图保存为图片等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值